import React, { useEffect, useRef } from 'react';
import { Cell, Graph, Path } from '@antv/x6';
import '@antv/x6-react-shape';
import './index.less';
import { transform } from '@/component/x6/util';
import { initData } from '@/component/x6/testdata';

function AlgoNode(props: any) {
  const { node } = props;
  const data = node.getData();
  const { label } = data;

  return (
    <div className={`node success`}>
      <span className="label">{label}</span>
    </div>
  );
}

Graph.registerNode(
  'dag-node',
  {
    inherit: 'react-shape',
    width: 180,
    height: 36,
    component: <AlgoNode />,
    ports: {
      groups: {
        top: {
          position: 'top',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#C2C8D5',
              strokeWidth: 1,
              fill: '#fff',
            },
          },
        },
        bottom: {
          position: 'bottom',
          attrs: {
            circle: {
              r: 4,
              magnet: true,
              stroke: '#C2C8D5',
              strokeWidth: 1,
              fill: '#fff',
            },
          },
        },
      },
    },
  },
  true,
);

Graph.registerEdge(
  'dag-edge',
  {
    inherit: 'edge',
    attrs: {
      line: {
        stroke: '#C2C8D5',
        strokeWidth: 1,
        targetMarker: null,
      },
    },
  },
  true,
);

Graph.registerConnector(
  'algo-connector',
  (s, e) => {
    const offset = 4;
    const deltaY = Math.abs(e.y - s.y);
    const control = Math.floor((deltaY / 3) * 2);

    const v1 = { x: s.x, y: s.y + offset + control };
    const v2 = { x: e.x, y: e.y - offset - control };

    return Path.normalize(
      `M ${s.x} ${s.y}
       L ${s.x} ${s.y + offset}
       C ${v1.x} ${v1.y} ${v2.x} ${v2.y} ${e.x} ${e.y - offset}
       L ${e.x} ${e.y}
      `,
    );
  },
  true,
);

export default function X6(props: any) {
  const { data } = props;
  const ref = useRef<any>();
  const graph = useRef<Graph>();

  useEffect(() => {
    graph.current = new Graph({
      container: ref.current,
      width: 800,
      height: 600,
      panning: false,
      mousewheel: {
        enabled: true,
        modifiers: 'ctrl',
        factor: 1.1,
        maxScale: 1.5,
        minScale: 0.5,
      },
      interacting: false,
      highlighting: {
        magnetAdsorbed: {
          name: 'stroke',
          args: {
            attrs: {
              fill: '#fff',
              stroke: '#31d0c6',
              strokeWidth: 4,
            },
          },
        },
      },
      connecting: {
        snap: true,
        allowBlank: false,
        allowLoop: false,
        highlight: true,
        connector: 'algo-connector',
        connectionPoint: 'anchor',
        anchor: 'center',
        validateMagnet({ magnet }) {
          return magnet.getAttribute('port-group') !== 'top';
        },
        createEdge() {
          return graph.current!.createEdge({
            shape: 'dag-edge',
            attrs: {
              line: {
                strokeDasharray: '5 5',
              },
            },
            zIndex: -1,
          });
        },
      },
    });
  }, []);

  useEffect(() => {
    if (data) {
      init(transform(data));
      graph.current!.centerContent();
    }
  }, [data]);

  const init = (data: Cell.Metadata[]) => {
    const cells: Cell[] = [];
    data.forEach((item) => {
      if (item.shape === 'dag-node') {
        cells.push(graph.current!.createNode(item));
      } else {
        cells.push(graph.current!.createEdge(item));
      }
    });
    graph.current!.resetCells(cells);
  };

  function scale() {
    graph.current!.zoom(0.1);
  }

  return (
    <>
      <button onClick={scale}>scale</button>
      <div ref={ref} />
    </>
  );
}
